package com.powergisol.gis.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.enums.WriteDirectionEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.excel.write.metadata.fill.FillWrapper;
import com.powergisol.gis.dao.TabZkMapper;
import com.powergisol.gis.entity.*;
import com.powergisol.gis.exception.GlobalExceptionHandler;
import com.powergisol.gis.service.ExcelExService;
import com.powergisol.gis.service.TabDataSettingService;
import com.powergisol.gis.service.TabProjectService;
import com.powergisol.gis.thread.Worker;
import com.powergisol.gis.util.ListUtil;
import com.powergisol.gis.util.ZipUtil;
import com.powergisol.gis.util.ZipUtils;
import com.powergisol.gis.vo.ExportExcelVO;
import com.powergisol.gis.vo.RandomExportVO;
import com.powergisol.gis.vo.TuCengVO;
import com.powergisol.gis.vo.ZuankongVO;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.*;


@Service

public class ExcelExServiceImpl implements ExcelExService {
    @Autowired
    private TabZkMapper tabZkMapper;

    //最终生成的zip文件的存放位置
    @Value("${file.zip-path}")
    String zipPath;

    //临时生成的excel文件的存放位置
    @Value("${file.temp-excel-path}")
    String tempFilePath;
    @Value("${file.excel-path}")
    String excelPath;
    @Autowired
    TabDataSettingService tabDataSettingService;
    @Autowired
    TabProjectService tabProjectService;
    @Autowired
    CacheManager cacheManager;
    private Integer maxNum = 100;

    /**
     * 文件导出
     *
     * @param ServiceID
     */
    @Override
    public void excelExportFiles(List<Integer> ServiceID, HttpServletResponse response) {
        List<TabDataSetting> dataSettings = tabDataSettingService.getSetIdBySerID(ServiceID);
        if (dataSettings.isEmpty() && dataSettings.size() <= 0) {
            return;
        }
        List<String> settingIds = new ArrayList<>();
        dataSettings.forEach(x -> {
            settingIds.add(String.valueOf(x.getId()));
        });
        List<TabZuankong> tabZuankongList = tabZkMapper.getZKBySettingId(settingIds);
        Map<String, List<TabZuankong>> stringListMap = ListUtil.splitList(tabZuankongList, maxNum);
        List<String> uuids = new ArrayList<>();
        String dirPath = tempFilePath + File.separator + UUID.randomUUID().toString().replaceAll("-", "");
        File dirFile = new File(dirPath);
        if (stringListMap.size()<=0 || stringListMap.isEmpty()) {
            throw  new GlobalExceptionHandler(400,"该服务下无钻孔数据");
        }
        stringListMap.forEach((x, y) -> {
            String uuid = UUID.randomUUID().toString().replaceAll("-", "");
            new Worker(y, cacheManager, tabProjectService, tabZkMapper, uuid, dirPath).start();
            uuids.add(uuid);
        });
        int tempNum = 0;
        do {
            Cache cache = cacheManager.getCache("cache-data");
            for (int i = 0; i < uuids.size(); i++) {
                if (cache.get(uuids.get(i), Integer.class) != null) {
                    tempNum += cache.get(uuids.get(i), Integer.class);
                    uuids.remove(i);
                    i--;
                }
            }
        } while (tempNum < tabZuankongList.size());
        System.out.println("结果数：" + tempNum);
        try {
            String filePath = zipPath + File.separator + System.currentTimeMillis() + ".zip";
            File file = new File(filePath);
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }
            ZipUtil.singleFileCompress(dirPath, filePath, null);
            ZipUtils.estampDown(file, response);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                FileUtils.deleteDirectory(dirFile);
            } catch (IOException ioException) {
                ioException.printStackTrace();
                throw new GlobalExceptionHandler(500, "临时文件删除失败");
            }
        }
    }

    @Override
    public void excelExportFilesTwo(List<Integer> ServiceID, HttpServletResponse response) throws RuntimeException {

        List<TabDataSetting> dataSettings = tabDataSettingService.getSetIdBySerID(ServiceID);
        if (dataSettings.isEmpty() && dataSettings.size() <= 0) {
            throw new GlobalExceptionHandler("数据不存在");
        }
        List<String> settingIds = new ArrayList<>();
        List<TabProject> tabProjects = new ArrayList<>();
        dataSettings.forEach(x -> {
            settingIds.add(String.valueOf(x.getId()));
            TabProject one = tabProjectService.getOne(x.getId());
            tabProjects.add(one);
        });

        List<TabZuankong> tabZuankongList = tabZkMapper.getZKBySettingId(settingIds);

        if(tabZuankongList.size()<=0 || tabZuankongList.isEmpty()){
            throw  new GlobalExceptionHandler(400,"该服务下无钻孔数据");
        }

        List<ExportExcelVO> exportExcelVOs = new ArrayList<>();

        tabZuankongList.forEach(z -> {
            List<ExportExcelVO> exportExcelVOList = new ArrayList<>();

            TabZkTuceng tabZkTuceng = new TabZkTuceng();
            tabZkTuceng.setSettingId(z.getSettingId());
            tabZkTuceng.setZKBH(z.getZKBH());
            List<TabZkTuceng> tcs = tabZkMapper.getTCS(tabZkTuceng);

            ExportExcelVO exportExcelVO = null;
            BigDecimal sd = new BigDecimal(0);
            for (TabZkTuceng tc : tcs) {
                sd = sd.add(tc.getTCHD());
            }
            for (TabZkTuceng c : tcs) {
                exportExcelVO = new ExportExcelVO();
                exportExcelVO.setSettingId(z.getSettingId() + "");
                exportExcelVO.setZKBH(z.getZKBH());
                if (z.getZKSD() == null || z.getZKSD() == new BigDecimal(0)) {
                    exportExcelVO.setZKSD(sd);
                } else {
                    exportExcelVO.setZKSD(z.getZKSD());
                }
                exportExcelVO.setZKKSRQ(dataValidation(z.getZKKSRQ()));
                exportExcelVO.setZKZZRQ(dataValidation(z.getZKZZRQ()));
                exportExcelVO.setTCCDSD(c.getTCCDSD());
                exportExcelVO.setTCHD(c.getTCHD());
                exportExcelVO.setTCXH(c.getTCXH());
                exportExcelVO.setCDGC(checkData(z.getZKBG(),c.getTCCDSD()));
                exportExcelVO.setTCDCBH(dataValidation(c.getTCBH()));
                exportExcelVO.setTCZCBH(c.getTCZCBH());
                exportExcelVO.setTCYCBH(c.getTCYCBH());
                exportExcelVO.setTCCYCBH(c.getTCCYCBH());
                exportExcelVO.setTCSDCY(dataValidation(c.getTCSDCY()));
                exportExcelVO.setTCDZSD(dataValidation(c.getTCDZSD()));
                exportExcelVO.setTCDZCY(dataValidation(c.getTCDZCY()));
                exportExcelVO.setTCDCHD(dataValidation(c.getTCDCHD()));
                exportExcelVO.setTCMC(dataValidation(c.getTCMC()));
                exportExcelVO.setTCMS(dataValidation(c.getTCMS()));
                exportExcelVO.setTCLM(dataValidation(c.getTCLM()));
                exportExcelVO.setKKGC(z.getZKBG());
                exportExcelVO.setKTDLX(dataValidation(z.getZKLX()));
                exportExcelVO.setZKX(null == z.getZKOX()?z.getZKX():z.getZKOX());
                exportExcelVO.setZKY(null == z.getZKOY()?z.getZKY():z.getZKOY());
                exportExcelVOList.add(exportExcelVO);
            }
            TabZkShuiwei tabZkShuiwei = new TabZkShuiwei();
            tabZkShuiwei.setZKBH(z.getZKBH());
            tabZkShuiwei.setSettingId(z.getSettingId());
            List<TabZkShuiwei> sws = tabZkMapper.getSWS(tabZkShuiwei);
            for (TabZkShuiwei s : sws) {
                for (ExportExcelVO excelVO : exportExcelVOList) {
                    if ((s.getSettingId() + "").equals(excelVO.getSettingId()) && s.getZKBH().equals(excelVO.getZKBH())) {
                        excelVO.setWDSWSD(s.getSWSD());
                    }
                }
            }
            exportExcelVOs.addAll(exportExcelVOList);
        });
        for (TabProject tabProject : tabProjects) {
            for (ExportExcelVO exportExcelVO : exportExcelVOs) {
                if ((tabProject.getSettingId() + "").equals(exportExcelVO.getSettingId())) {
                    exportExcelVO.setGCMC(dataValidation(tabProject.getGCMC()));
                    exportExcelVO.setGCBH(dataValidation(tabProject.getGCBH()));
                }
            }
        }
        String fileName = excelPath + File.separator + tabProjects.get(0).getGCMC() + ".xlsx";
        File file = new File(fileName);
        File parentFile = file.getParentFile();
        if (!parentFile.exists()) {
            parentFile.mkdirs();
        }
        //开始文件写入
        EasyExcel.write(fileName, ExportExcelVO.class).sheet("Sheet1").doWrite(exportExcelVOs);
        ZipUtils.estampDown(file, response);
    }

    @Override
    public void randomExportFiles(List<RandomExportVO> randomExportVOS, HttpServletResponse response) {
        List<File> files = new ArrayList<>();
        for (RandomExportVO randomExportVO : randomExportVOS) {
            ZuankongVO zKs = new ZuankongVO();
            List<ZuankongVO> zuanKS = tabZkMapper.getZuanKS(randomExportVO.getSettingId());
//            ZuankongVO zKs = tabZkMapper.getZKs(randomExportVO.getSettingId(), randomExportVO.getZkbh());
            zuanKS.forEach(z->{
                if(z.getZKBH().equals(randomExportVO.getZkbh())){
                    BeanUtils.copyProperties(z,zKs);
                }
            });

            if (zKs.getZKLX().contains("　")) {
                zKs.setZKLX(zKs.getZKLX().replace("　", ""));
            }
            List<TuCengVO> tc = tabZkMapper.getTcs(randomExportVO.getSettingId(), randomExportVO.getZkbh());
            BigDecimal sd = new BigDecimal(0);
            for (TuCengVO t : tc) {
                sd = sd.add(t.getTCHD());
                t.setTCBH(dataValidation(t.getTCBH()));
                t.setTCDZSD(dataValidation(t.getTCDZSD()));
                t.setTCDZCY(dataValidation(t.getTCDZCY()));
                t.setTCDCHD(dataValidation(t.getTCDCHD()));
                t.setTCSDCY(dataValidation(t.getTCSDCY()));
                t.setTCLM(dataValidation(t.getTCLM()));
                t.setTCMS(dataValidation(t.getTCMS()));
            }
            List<TabZkShuiwei> sw = tabZkMapper.getSws(randomExportVO.getSettingId(), randomExportVO.getZkbh());
            Resource resource = new ClassPathResource("template/template1.1.xlsx");
            TabProject one = tabProjectService.getOne(randomExportVO.getSettingId());
            Serializable serializable = one != null ? one.getGCMC() : System.currentTimeMillis();
            String fileName = tempFilePath + File.separator + serializable + "_" + zKs.getZKBH() + ".xlsx";
            File file = new File(fileName);
            File parentFile = file.getParentFile();
            if (!parentFile.exists()) {
                parentFile.mkdirs();
            }
            files.add(file);
            ExcelWriter excelWriter = null;
            try {
                excelWriter = EasyExcel.write(fileName).withTemplate(resource.getInputStream()).build();
            } catch (IOException e) {
                e.printStackTrace();
            }

            WriteSheet writeSheet = EasyExcel.writerSheet().build();

            FillConfig fillConfig = FillConfig.builder().direction(WriteDirectionEnum.HORIZONTAL).build();
            excelWriter.fill(new FillWrapper("TabZkTuceng", tc), fillConfig, writeSheet);
            excelWriter.fill(new FillWrapper("TabZkShuiwei", sw), fillConfig, writeSheet);

            Map<String, Object> map = new HashMap<>();
            map.put("ZKBH", zKs.getZKBH());
            map.put("ZKX", null == zKs.getZKOX()?zKs.getZKX():zKs.getZKOX());
            map.put("ZKY", null == zKs.getZKOY()?zKs.getZKY():zKs.getZKOY());
            map.put("ZKBG", zKs.getZKBG());
            map.put("ZKZJ", zKs.getZKZJ());
            if (zKs.getZKSD() == null || zKs.getZKSD() == new BigDecimal(0)) {
                map.put("ZKSD", sd);
            } else {
                map.put("ZKSD", zKs.getZKSD());
            }
            map.put("tuceng", tc.size());
            map.put("shuiwei", sw.size());
            map.put("ZKLX", dataValidation(zKs.getZKLX()));
            map.put("ZKPZTSDXS", zKs.getZKPZTSDXS());
            map.put("GCBH", dataValidation(one.getGCBH()));
            map.put("ZKKSRQ", dataValidation(zKs.getZKKSRQ()));
            map.put("ZKZZRQ", dataValidation(zKs.getZKZZRQ()));
            map.put("Hcdm01", zKs.getHcdm01());
            map.put("Hcdm02", zKs.getHcdm02());
            map.put("Hcdm05", zKs.getHcdm05());
            excelWriter.fill(map, writeSheet);
            // 别忘记关闭流
            excelWriter.finish();

        }
        if (!files.isEmpty() && files.size() > 0) {
            try {
                File zipfile = new File(zipPath + File.separator + System.currentTimeMillis() + ".zip");
                File parentFile = zipfile.getParentFile();
                if (!parentFile.exists()) {
                    parentFile.mkdirs();
                }
                ZipUtils.toZip(files, zipfile);
                ZipUtils.estampDown(zipfile, response);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                files.forEach(f -> {
                    FileUtils.deleteQuietly(f);
                });
            }
        }
    }

    @Override
    public void randomExportFilesTWO(List<RandomExportVO> randomExportVOS, HttpServletResponse response) {
        List<ExportExcelVO> exportExcelVOs = new ArrayList<>();
        TabProject one = null;
        for (RandomExportVO randomExportVO : randomExportVOS) {
            one = tabProjectService.getOne(randomExportVO.getSettingId());

            List<ExportExcelVO> exportExcelVOList = new ArrayList<>();
//            ZuankongVO z = tabZkMapper.getZKs(randomExportVO.getSettingId(), randomExportVO.getZkbh());
            ZuankongVO z = new ZuankongVO();
            List<ZuankongVO> zuanKS = tabZkMapper.getZuanKS(randomExportVO.getSettingId());
            for (ZuankongVO c : zuanKS) {
                if(c.getZKBH().equals(randomExportVO.getZkbh())){
                    BeanUtils.copyProperties(c,z);
                }
            }

            List<TuCengVO> tcs = tabZkMapper.getTcs(randomExportVO.getSettingId(), randomExportVO.getZkbh());
            ExportExcelVO exportExcelVO = null;
            BigDecimal sd = new BigDecimal(0);
            for (TuCengVO tc : tcs) {
                sd = sd.add(tc.getTCHD());
            }
            for (TabZkTuceng c : tcs) {
                exportExcelVO = new ExportExcelVO();
                exportExcelVO.setSettingId(z.getSettingId() + "");
                exportExcelVO.setZKBH(z.getZKBH());
                if (z.getZKSD() == null || z.getZKSD() == new BigDecimal(0)) {
                    exportExcelVO.setZKSD(sd);
                } else {
                    exportExcelVO.setZKSD(z.getZKSD());
                }
                exportExcelVO.setZKKSRQ(dataValidation(z.getZKKSRQ()));
                exportExcelVO.setZKZZRQ(dataValidation(z.getZKZZRQ()));
                exportExcelVO.setTCCDSD(c.getTCCDSD());
                exportExcelVO.setTCHD(c.getTCHD());
                exportExcelVO.setTCXH(c.getTCXH());
                exportExcelVO.setCDGC(checkData(z.getZKBG(),c.getTCCDSD()));
                exportExcelVO.setTCDCBH(dataValidation(c.getTCBH()));
                exportExcelVO.setTCZCBH(c.getTCZCBH());
                exportExcelVO.setTCYCBH(c.getTCYCBH());
                exportExcelVO.setTCCYCBH(c.getTCCYCBH());
                exportExcelVO.setTCSDCY(dataValidation(c.getTCSDCY()));
                exportExcelVO.setTCDZSD(dataValidation(c.getTCDZSD()));
                exportExcelVO.setTCDZCY(dataValidation(c.getTCDZCY()));
                exportExcelVO.setTCDCHD(dataValidation(c.getTCDCHD()));
                exportExcelVO.setTCMC(dataValidation(c.getTCMC()));
                exportExcelVO.setTCMS(dataValidation(c.getTCMS()));
                exportExcelVO.setTCLM(dataValidation(c.getTCLM()));
                exportExcelVO.setKKGC(z.getZKBG());
                exportExcelVO.setKTDLX(dataValidation(z.getZKLX()));
                exportExcelVO.setZKX(z.getZKOX());
                exportExcelVO.setZKY(z.getZKOY());
                exportExcelVO.setGCMC(dataValidation(one.getGCMC()));
                exportExcelVO.setGCBH(dataValidation(one.getGCBH()));

                exportExcelVOList.add(exportExcelVO);
            }
            List<TabZkShuiwei> sws = tabZkMapper.getSws(randomExportVO.getSettingId(), randomExportVO.getZkbh());
            if (!sws.isEmpty() && sws.size() >= 0) {
                for (TabZkShuiwei s : sws) {
                    for (ExportExcelVO excelVO : exportExcelVOList) {
                        if ((s.getSettingId() + "").equals(excelVO.getSettingId()) && s.getZKBH().equals(excelVO.getZKBH())) {
                            excelVO.setWDSWSD(s.getSWSD());
                        }
                    }
                }
            }
            exportExcelVOs.addAll(exportExcelVOList);
        }
        Serializable serializable = one != null ? one.getGCMC() : System.currentTimeMillis();
        String fileName = excelPath + File.separator + serializable + ".xlsx";
        File file = new File(fileName);
        File parentFile = file.getParentFile();
        if (!parentFile.exists()) {
            parentFile.mkdirs();
        }
        //开始文件写入
        EasyExcel.write(fileName, ExportExcelVO.class).sheet("Sheet1").doWrite(exportExcelVOs);
        ZipUtils.estampDown(file, response);
    }
    private String dataValidation(String str){
        if(str == null){
            return null;
        }else if(str.trim().equals("null")){
            return null;
        }else{
            return str.trim();
        }
    }

    private BigDecimal checkData(BigDecimal num1,BigDecimal num2){
        if(num1==null || num1==new BigDecimal(0)){
            return null;
        }else if(num2==null || num2==new BigDecimal(0)){
            return num1;
        }else{
            return num1.subtract(num2);
        }
    }

}


